package cn.dansj.common.utils.calendar;

import cn.dansj.common.utils.json.JSONObject;
import cn.dansj.common.utils.transfer.*;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 计算农历节假日信息
 * CalendarUtils.Calendar calendar=CalendarUtils.getCalendar("2019-06-06");
 */
@SuppressWarnings("deprecation")
public class CalendarUtils {
    private static final long[] lunarInfo = new long[]{
            0x4bd8, 0x4ae0, 0xa570, 0x54d5, 0xd260, 0xd950, 0x5554, 0x56af, 0x9ad0, 0x55d2,
            0x4ae0, 0xa5b6, 0xa4d0, 0xd250, 0xd255, 0xb54f, 0xd6a0, 0xada2, 0x95b0, 0x4977,
            0x497f, 0xa4b0, 0xb4b5, 0x6a50, 0x6d40, 0xab54, 0x2b6f, 0x9570, 0x52f2, 0x4970,
            0x6566, 0xd4a0, 0xea50, 0x6a95, 0x5adf, 0x2b60, 0x86e3, 0x92ef, 0xc8d7, 0xc95f,
            0xd4a0, 0xd8a6, 0xb55f, 0x56a0, 0xa5b4, 0x25df, 0x92d0, 0xd2b2, 0xa950, 0xb557,
            0x6ca0, 0xb550, 0x5355, 0x4daf, 0xa5b0, 0x4573, 0x52bf, 0xa9a8, 0xe950, 0x6aa0,
            0xaea6, 0xab50, 0x4b60, 0xaae4, 0xa570, 0x5260, 0xf263, 0xd950, 0x5b57, 0x56a0,
            0x96d0, 0x4dd5, 0x4ad0, 0xa4d0, 0xd4d4, 0xd250, 0xd558, 0xb540, 0xb6a0, 0x95a6,
            0x95bf, 0x49b0, 0xa974, 0xa4b0, 0xb27a, 0x6a50, 0x6d40, 0xaf46, 0xab60, 0x9570,
            0x4af5, 0x4970, 0x64b0, 0x74a3, 0xea50, 0x6b58, 0x5ac0, 0xab60, 0x96d5, 0x92e0,
            0xc960, 0xd954, 0xd4a0, 0xda50, 0x7552, 0x56a0, 0xabb7, 0x25d0, 0x92d0, 0xcab5,
            0xa950, 0xb4a0, 0xbaa4, 0xad50, 0x55d9, 0x4ba0, 0xa5b0, 0x5176, 0x52bf, 0xa930,
            0x7954, 0x6aa0, 0xad50, 0x5b52, 0x4b60, 0xa6e6, 0xa4e0, 0xd260, 0xea65, 0xd530,
            0x5aa0, 0x76a3, 0x96d0, 0x4afb, 0x4ad0, 0xa4d0, 0xd0b6, 0xd25f, 0xd520, 0xdd45,
            0xb5a0, 0x56d0, 0x55b2, 0x49b0, 0xa577, 0xa4b0, 0xaa50, 0xb255, 0x6d2f, 0xada0,
            0x4b63, 0x937f, 0x49f8, 0x4970, 0x64b0, 0x68a6, 0xea5f, 0x6b20, 0xa6c4, 0xaaef,
            0x92e0, 0xd2e3, 0xc960, 0xd557, 0xd4a0, 0xda50, 0x5d55, 0x56a0, 0xa6d0, 0x55d4,
            0x52d0, 0xa9b8, 0xa950, 0xb4a0, 0xb6a6, 0xad50, 0x55a0, 0xaba4, 0xa5b0, 0x52b0,
            0xb273, 0x6930, 0x7337, 0x6aa0, 0xad50, 0x4b55, 0x4b6f, 0xa570, 0x54e4, 0xd260,
            0xe968, 0xd520, 0xdaa0, 0x6aa6, 0x56df, 0x4ae0, 0xa9d4, 0xa4d0, 0xd150, 0xf252,
            0xd520};
    List<Calendar> calendars = new ArrayList<>();
    private static final Map<String, CalendarUtils> cache = new HashMap<>();
    private static final long[] solarMonth = new long[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    private static final String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
    private static final String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
    private static final String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};
    private static final String[] solarTerm = new String[]{"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};
    private static final int[] sTermInfo = new int[]{0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758};
    private static final char[] nStr1 = new char[]{'日', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'};
    private static final String[] nStr2 = new String[]{"初", "十", "廿", "卅", " "};
    private static final JSONObject zodiac = JSONObject.of("白羊座", new String[]{"3.21", "4.19"},
            "金牛座", new String[]{"4.20", "5.20"},
            "双子座", new String[]{"5.21", "6.21"},
            "巨蟹座", new String[]{"6.22", "7.22"},
            "狮子座", new String[]{"7.23", "8.22"},
            "处女座", new String[]{"8.23", "9.22"},
            "天秤座", new String[]{"9.23", "10.23"},
            "天蝎座", new String[]{"10.24", "11.22"},
            "射手座", new String[]{"11.23", "12.21"},
            "摩羯座", new String[]{"12.22", "1.19"},
            "水瓶座", new String[]{"1.20", "2.18"},
            "双鱼座", new String[]{"2.19", "3.20"});

    private static final String[] monthChinese = new String[]{"正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"};

    //国历节日
    private static final JSONObject sFtv = JSONObject.of("0101", "元旦节",
            "0214", "情人节",
            "0308", "妇女节",
            "0312", "植树节", "孙中山逝世纪念日",
            "0315", "消费者权益保护日",
            "0401", "愚人节",
            "0501", "劳动节",
            "0504", "青年节",
            "0519", "汶川地震哀悼日",
            "0601", "儿童节",
            "0701", "建党节", "香港回归纪念日",
            "0707", "抗日战争纪念日",
            "0801", "八一建军节",
            "0815", "日本正式宣布无条件投降日",
            "0909", "毛主席逝世纪念日",
            "0910", "教师节",
            "0918", "九·一八事变纪念日",
            "0928", "孔子诞辰",
            "1001", "国庆节",
            "1010", "辛亥革命纪念日",
            "1031", "万圣节",
            "1112", "孙中山诞辰",
            "1212", "西安事变纪念日",
            "1213", "南京大屠杀",
            "1220", "澳门回归纪念日",
            "1224", "平安夜",
            "1225", "圣诞节",
            "1226", "毛主席诞辰");
    //农历节日
    private static final JSONObject lFtv = JSONObject.of("0101", "春节",
            "0115", "元宵节",
            "0202", "龙抬头",
            "0404", "寒食节",
            "0505", "端午节",
            "0624", "火把节",
            "0707", "七夕情人节",
            "0714", "鬼节(南方)",
            "0715", "中元节",
            "0730", "地藏节",
            "0815", "中秋节",
            "0909", "重阳节",
            "1001", "寒衣节",
            "1015", "下元节",
            "1208", "腊八节",
            "1223", "北方小年",
            "1224", "南方小年",
            "1230", "除夕");

    private CalendarUtils() {
    }

    public static Calendar getCalendar(Date date) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(date);
        int year = cal.get(java.util.Calendar.YEAR);
        int month = cal.get(java.util.Calendar.MONTH);
        String cacheKey = year + "-" + month;
        CalendarUtils calendarUtils = cache.get(cacheKey);
        if (calendarUtils == null) {
            calendarUtils = new CalendarUtils();
            try {
                calendarUtils.calendar(year, month);
            } catch (ParseException e) {
                throw new IllegalArgumentException();
            }
            cache.put(cacheKey, calendarUtils);
        }
        return calendarUtils.getCalendars().get(cal.get(java.util.Calendar.DATE) - 1);
    }

    public static List<Calendar> getCalendars(int year) {
        return IntStream.range(1, 13).mapToObj(e -> CalendarUtils.getCalendars(year, e)).flatMap(Collection::stream).collect(Collectors.toList());
    }

    public static List<Calendar> getCalendars(int year, int month) {
        String cacheKey = year + "-" + month;
        CalendarUtils calendarUtils = cache.get(cacheKey);
        if (calendarUtils == null) {
            calendarUtils = new CalendarUtils();
            try {
                calendarUtils.calendar(year, month - 1);
            } catch (ParseException e) {
                throw new IllegalArgumentException();
            }
            cache.put(cacheKey, calendarUtils);
        }
        return calendarUtils.getCalendars();
    }

    public static Calendar getCalendar(String date) {
        return getCalendar(DateTime.getInstance(date).toDate());
    }

    public List<Calendar> getCalendars() {
        return calendars;
    }

    public void setCalendars(List<Calendar> calendars) {
        this.calendars = calendars;
    }

    private void calendar(int y, int m) throws ParseException {
        Date sDObj;
        Lunar lDObj;
        boolean lL = false;
        int lY = 0, lM = 0, lD = 1, lX = 0, tmp1, tmp2;
        String cY, cM, cD; //年柱,月柱,日柱
        //公历当月天数
        long length = solarDays(y, m);    //公历当月天数
        ////////年柱 1900年立春后为庚子年(60进制36)
        if (m < 2) cY = cyclical(y - 1900 + 36 - 1);
        else cY = cyclical(y - 1900 + 36);
        int term2 = sTerm(y, 2); //立春日期
        ////////月柱 1900年1月小寒以前为 丙子月(60进制12)
        int firstNode = sTerm(y, m * 2);//返回当月「节」为几日开始
        cM = cyclical((y - 1900) * 12L + m + 12);
        //当月一日与 1900/1/1 相差天数
        //1900/1/1与 1970/1/1 相差25567日, 1900/1/1 日柱为甲戌日(60进制10)
        SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        df2.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = df2.parse(y + "-" + (m + 1) + "-" + 1 + " 00:00:00");
        long dayCyclical = date.getTime() / 86400000 + 25567 + 10;
        SimpleDateFormat df3 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        for (int i = 0; i < length; i++) {
            sDObj = df3.parse(y + "-" + (m + 1) + "-" + (i + 1) + " 00:00:00");   //当月一日日期
            if (lD > lX) {
                lDObj = new Lunar(sDObj);     //农历
                lY = lDObj.year;           //农历年
                lM = lDObj.month;          //农历月
                lD = lDObj.day;            //农历日
                lL = lDObj.leap;         //农历是否闰月
                lX = lL ? leapDays(lY) : monthDays(lY, lM); //农历当月最后一天
            }

            //依节气调整二月分的年柱, 以立春为界
            if (m == 1 && (i + 1) == term2) {
                cY = cyclical(y - 1900 + 36);
            }
            //依节气月柱, 以「节」为界
            if ((i + 1) == firstNode) {
                cM = cyclical((y - 1900) * 12L + m + 13);
            }
            //日柱
            cD = cyclical(dayCyclical + i);

            Calendar calendar = new Calendar(y, m + 1, i + 1, lY, lM, lD++, lL, cY, cM, cD, sDObj.getDay());//y, m + 1, i + 1
            calendar.setlDayChinese(cDay(calendar.getlDay()));
            String ltvString = lFtv.getString(StringUtils.padLeft(calendar.lMonth, 2, '0') + StringUtils.padLeft(calendar.lDay, 2, '0'));
            String stvString = sFtv.getString(StringUtils.padLeft(calendar.sMonth, 2, '0') + StringUtils.padLeft(calendar.sDay, 2, '0'));
            //阳历节日
            calendar.solarFestival += (Verification.checkNull(stvString) ? "" : stvString);
            //阴历节日
            calendar.lunarFestival += (Verification.checkNull(ltvString) ? "" : ltvString);
            calendars.add(calendar);
        }

        //节气
        tmp1 = sTerm(y, m * 2) - 1;
        tmp2 = sTerm(y, m * 2 + 1) - 1;
        calendars.get(tmp1).solarTerms = solarTerm[m * 2];
        calendars.get(tmp2).solarTerms = solarTerm[m * 2 + 1];

        // 处理非节气日显示"上一个节气后"
        String lastTerm;
        // 获取上个月的最后一个节气（如果是1月则为上一年12月的冬至）
        if (m > 0) {
            int lastMonthTerm2 = sTerm(y, (m - 1) * 2 + 1) - 1;
            int lastMonthDays = (int) solarDays(y, m - 1);
            if (lastMonthTerm2 < lastMonthDays) {
                lastTerm = solarTerm[(m - 1) * 2 + 1];
            } else {
                lastTerm = solarTerm[(m - 1) * 2];
            }
        } else {
            // 1月份的上一个节气是冬至
            lastTerm = solarTerm[23]; // 冬至是第24个节气(数组下标23)
        }

        // 处理本月的节气显示
        for (Calendar calendar : calendars) {
            if (!calendar.solarTerms.isEmpty()) {
                // 如果是节气日，更新lastTerm
                lastTerm = calendar.solarTerms;
            } else {
                // 如果不是节气日且有上一个节气，显示"节气后"
                calendar.solarTerms = lastTerm + "后";
            }
        }

        //复活节只出现在3或4月
        if (m == 2 || m == 3) {
            Easter estDay = new Easter(y);
            if (m == estDay.m)
                calendars.get(estDay.d - 1).solarFestival = calendars.get(estDay.d - 1).solarFestival + " 复活节";
        }
    }

    //==============================返回公历 y年某m+1月的天数
    public long solarDays(int y, int m) {
        if (m == 1)
            return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28);
        else
            return (solarMonth[m]);
    }

    //============================== 传入 offsenew Datet 返回干支, 0=甲子
    public String cyclical(long num) {
        return (Gan[(int) (num % 10)] + Zhi[(int) (num % 12)]);
    }

    //======================  中文日期
    public String cDay(int d) {
        String s;
        switch (d) {
            case 10:
                s = "初十";
                break;
            case 20:
                s = "二十";
                break;
            case 30:
                s = "三十";
                break;
            default:
                s = nStr2[Double.valueOf(Math.floor((double) d / 10)).intValue()];
                s += nStr1[d % 10];
        }
        return (s);
    }

    //===== 某年的第n个节气为几日(从0小寒起算)
    public int sTerm(int y, int n) {
        SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df2.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date;
        try {
            date = df2.parse("1900-01-06 02:05:00");
        } catch (ParseException e) {
            throw new IllegalArgumentException();
        }
        long utcTime2 = date.getTime();
        BigDecimal time2 = new BigDecimal("31556925974.7").multiply(new BigDecimal(y - 1900)).add(new BigDecimal(sTermInfo[n]).multiply(BigDecimal.valueOf(60000L)));
        BigDecimal time = time2.add(BigDecimal.valueOf(utcTime2));
        Date offDate = new Date(time.longValue());
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone("UTC"));
        cal.setTime(offDate);
        //日期从0算起
        return cal.get(java.util.Calendar.DATE);
    }

    //====================================== 返回农历 y年闰哪个月 1-12 , 没闰返回 0
    public Long leapMonth(int y) {
        long lm = lunarInfo[y - 1900] & 0xf;
        return (lm == 0xf ? 0 : lm);
    }

    //====================================== 返回农历 y年的总天数
    public Long lYearDays(int y) {
        long i, sum = 348;
        for (i = 0x8000; i > 0x8; i >>= 1) sum += (lunarInfo[y - 1900] & i) != 0 ? 1 : 0;
        return (sum + leapDays(y));
    }

    //====================================== 返回农历 y年闰月的天数
    public int leapDays(int y) {
        if (leapMonth(y) != 0) return ((lunarInfo[y - 1899] & 0xf) == 0xf ? 30 : 29);
        else return 0;
    }

    //====================================== 返回农历 y年m月的总天数
    private int monthDays(int y, int m) {
        return ((lunarInfo[y - 1900] & (0x10000 >> m)) != 0 ? 30 : 29);
    }

    private static String[] getConstellation(int sMonth, int sDay) {
        for (Map.Entry<String, Object> entry : zodiac.entrySet()) {
            String[] date = (String[]) entry.getValue();
            String startDate = date[0];
            int startMonth = Integer.parseInt(startDate.substring(0, startDate.indexOf(".")));
            int startDay = Integer.parseInt(startDate.substring(startDate.indexOf(".") + 1));
            String endDate = date[1];
            int endMonth = Integer.parseInt(endDate.substring(0, endDate.indexOf(".")));
            int endDay = Integer.parseInt(endDate.substring(endDate.indexOf(".") + 1));
            if (startMonth == sMonth && sDay >= startDay || endMonth == sMonth && sDay <= endDay) {
                return new String[]{entry.getKey(), String.valueOf(ArrayUtils.asList(zodiac.keySet()).indexOf(entry.getKey()) + 1)};
            }
        }
        return new String[]{"", ""};
    }

    public class Lunar {
        private final int year;
        private boolean leap;
        private final int month;
        private final int day;

        public Lunar(Date objDate) throws ParseException {
            int i, leap, temp = 0;
            SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            df2.setTimeZone(TimeZone.getTimeZone("UTC"));
            DateFormat dtFmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            Date date = df2.parse(dtFmt.format(objDate));
            SimpleDateFormat df3 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            df3.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date3 = df3.parse(1900 + "-" + 1 + "-" + 31 + " 00:00:00");
            long time1 = date.getTime();
            long time2 = date3.getTime();
            int offset = (int) ((time1 - time2) / 86400000);
            for (i = 1900; i < 2100 && offset > 0; i++) {
                temp = lYearDays(i).intValue();
                offset -= temp;
            }

            if (offset < 0) {
                offset += temp;
                i--;
            }

            this.year = i;
            leap = leapMonth(i).intValue(); //闰哪个月
            this.leap = false;

            for (i = 1; i < 13 && offset > 0; i++) {
                //闰月
                if (leap > 0 && i == (leap + 1) && !this.leap) {
                    --i;
                    this.leap = true;
                    temp = leapDays(this.year);
                } else {
                    temp = monthDays(this.year, i);
                }

                //解除闰月
                if (this.leap && i == (leap + 1)) this.leap = false;

                offset -= temp;
            }

            if (offset == 0 && leap > 0 && i == leap + 1)
                if (this.leap) {
                    this.leap = false;
                } else {
                    this.leap = true;
                    --i;
                }

            if (offset < 0) {
                offset += temp;
                --i;
            }

            this.month = i;
            this.day = offset + 1;
        }
    }

    public class Easter {
        public int m;
        public int d;

        public Easter(int y) throws ParseException {
            int term2 = sTerm(y, 5); //取得春分日期
            SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            df2.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date dayTerm2 = df2.parse(y + "-" + 3 + "-" + term2 + " 00:00:00");//取得春分的公历日期控件(春分一定出现在3月)
            Lunar lDayTerm2 = new Lunar(dayTerm2); //取得取得春分农历
            int lMlen = lDayTerm2.day < 15 ? 15 - lDayTerm2.day : (lDayTerm2.leap ? leapDays(y) : monthDays(y, lDayTerm2.month)) - lDayTerm2.day + 15;
            //一天等于 1000*60*60*24 = 86400000 毫秒
            Date l15 = new Date(dayTerm2.getTime() + 86400000L * lMlen); //求出第一次月圆为公历几日
            Date dayEaster = new Date(l15.getTime() + 86400000 * (7 - l15.getDay())); //求出下个周日

            this.m = dayEaster.getMonth();
            this.d = dayEaster.getDate();
        }
    }

    public static class Calendar extends DefaultMethods {
        /**
         * 公历年
         */
        private int sYear;
        /**
         * 公历月
         */
        private int sMonth;
        /**
         * 公历日
         */
        private int sDay;
        /**
         * 星期几
         */
        private int week;
        /**
         * 农历年
         */
        private int lYear;
        /**
         * 农历月
         */
        private int lMonth;
        /**
         * 农历中文月
         */
        private String lMonthChinese;
        /**
         * 农历日
         */
        private int lDay;
        /**
         * 农历中文日
         */
        private String lDayChinese;
        /**
         * 是否闰月
         */
        private boolean leap;
        /**
         * 天干地支年
         */
        private String cYear;
        /**
         * 天干地支月
         */
        private String cMonth;
        /**
         * 天干地支日
         */
        private String cDay;
        /**
         * 农历节日
         */
        private String lunarFestival;
        /**
         * 公历节日
         */
        private String solarFestival;
        /**
         * 节气
         */
        private String solarTerms;
        /**
         * 公历完整日期
         */
        private String sDate;
        /**
         * 生肖
         */
        private final String chineseZodiac;
        /**
         * 星座
         */
        private final String zodiac;
        /**
         * 黄道宫
         */
        private final int zodiacSigns;
        /**
         * 一年的第几天
         */
        private final int dayOfYear;
        /**
         * 一年的第几周
         */
        private final int weekOfYear;
        /**
         * 月的第几周
         */
        private final int weekOfMonth;

        public Calendar(int sYear, int sMonth, int sDay, int lYear, int lMonth, int lDay, boolean leap, String cYear, String cMonth, String cDay, int week) {
            this.sDate = sYear + "-" + StringUtils.padLeft(sMonth, 2, '0') + "-" + StringUtils.padLeft(sDay, 2, '0');
            this.sYear = sYear;   //公元年4位数字
            this.sMonth = sMonth;  //公元月数字
            this.sDay = sDay;    //公元日数字
            //农历
            this.lYear = lYear;   //公元年4位数字
            this.lMonth = lMonth;  //农历月数字
            this.lDay = lDay;    //农历日数字
            this.leap = leap;  //是否为农历闰月?
            //中文
            this.lMonthChinese = monthChinese[lMonth - 1];
            //八字
            this.cYear = cYear;   //年柱, 2个中文
            this.cMonth = cMonth;  //月柱, 2个中文
            this.cDay = cDay;    //日柱, 2个中文

            this.lunarFestival = ""; //农历节日
            this.solarFestival = ""; //公历节日
            this.solarTerms = ""; //节气
            this.week = week == 0 ? 7 : week;

            this.chineseZodiac = Animals[(lYear - 1900) % 12];
            String[] constellations = getConstellation(sMonth, sDay);
            this.zodiac = constellations[0];
            this.zodiacSigns = Integer.parseInt(constellations[1]);
            DateTime dateTime = DateTime.getInstance(this.sDate);
            this.dayOfYear = dateTime.dayOfYear();
            this.weekOfYear = dateTime.weekOfYear();
            this.weekOfMonth = dateTime.weekOfMonth();
            if (sMonth == 5 && weekOfMonth == 2 && this.week == 7) this.solarFestival += "母亲节";
            if (sMonth == 6 && weekOfMonth == 3 && this.week == 7) this.solarFestival += "父亲节";
        }

        public int getsYear() {
            return sYear;
        }

        public void setsYear(int sYear) {
            this.sYear = sYear;
        }

        public int getsMonth() {
            return sMonth;
        }

        public void setsMonth(int sMonth) {
            this.sMonth = sMonth;
        }

        public int getsDay() {
            return sDay;
        }

        public void setsDay(int sDay) {
            this.sDay = sDay;
        }

        public int getlYear() {
            return lYear;
        }

        public void setlYear(int lYear) {
            this.lYear = lYear;
        }

        public int getlMonth() {
            return lMonth;
        }

        public void setlMonth(int lMonth) {
            this.lMonth = lMonth;
        }

        public int getlDay() {
            return lDay;
        }

        public void setlDay(int lDay) {
            this.lDay = lDay;
        }

        public int getWeek() {
            return week;
        }

        public void setWeek(int week) {
            this.week = week;
        }

        public boolean isLeap() {
            return leap;
        }

        public void setLeap(boolean leap) {
            this.leap = leap;
        }

        public String getcYear() {
            return cYear;
        }

        public void setcYear(String cYear) {
            this.cYear = cYear;
        }

        public String getcMonth() {
            return cMonth;
        }

        public void setcMonth(String cMonth) {
            this.cMonth = cMonth;
        }

        public String getcDay() {
            return cDay;
        }

        public void setcDay(String cDay) {
            this.cDay = cDay;
        }

        public String getLunarFestival() {
            return lunarFestival;
        }

        public void setLunarFestival(String lunarFestival) {
            this.lunarFestival = lunarFestival;
        }

        public String getSolarFestival() {
            return solarFestival;
        }

        public void setSolarFestival(String solarFestival) {
            this.solarFestival = solarFestival;
        }

        public String getSolarTerms() {
            return solarTerms;
        }

        public void setSolarTerms(String solarTerms) {
            this.solarTerms = solarTerms;
        }

        public String getlMonthChinese() {
            return lMonthChinese;
        }

        public void setlMonthChinese(String lMonthChinese) {
            this.lMonthChinese = lMonthChinese;
        }

        public String getlDayChinese() {
            return lDayChinese;
        }

        public void setlDayChinese(String lDayChinese) {
            this.lDayChinese = lDayChinese;
        }

        public String getsDate() {
            return sDate;
        }

        public void setsDate(String sDate) {
            this.sDate = sDate;
        }

        public String getChineseZodiac() {
            return chineseZodiac;
        }

        public String getZodiac() {
            return zodiac;
        }

        public int getZodiacSigns() {
            return zodiacSigns;
        }

        public int getDayOfYear() {
            return dayOfYear;
        }

        public int getWeekOfMonth() {
            return weekOfMonth;
        }

        public int getWeekOfYear() {
            return weekOfYear;
        }

        public String getlDateChinese() {
            return (this.isLeap() ? "闰" : "") + this.lMonthChinese + this.lDayChinese;
        }
    }
}